import { Body, Controller, DefaultValuePipe, Get, Inject, Logger, Post, Query, Req, UnauthorizedException } from '@nestjs/common'
import { EmailService } from 'src/email/email.service'
import { RedisService } from 'src/redis/redis.service'
import { JwtService } from '@nestjs/jwt'
import { RequireLogin, RequirePermission, UserInfo } from 'src/custom/decorator'
import { formatDate, generateParseIntPipe } from 'src/utils'
import { Request } from 'express'
import { UserService } from './user.service'
import { RegisterUserDto } from './dto/register-user.dto'
import { LoginUserDto } from './dto/login-user.dto'
import { RefreshTokenVo } from './vo/refresh-token.vo'
import { UpdateUserPasswordDto } from './dto/update-user-password.dto'
import { UpdateUserDto } from './dto/update-user.dto'

@Controller('user')
export class UserController {
  private logger = new Logger()

  constructor(private readonly userService: UserService) { }

  @Inject(EmailService)
  private emailService: EmailService

  @Inject(RedisService)
  private redisService: RedisService

  @Inject(JwtService)
  private jwtService: JwtService

  @Get('init-data')
  async initData() {
    await this.userService.initData()
    return 'init done'
  }

  @Post('register')
  async register(@Body() registerUser: RegisterUserDto) {
    return await this.userService.register(registerUser)
  }

  @Get('register-captcha')
  async captcha(@Query('address') address: string) {
    const code = Math.random().toString().slice(2, 8)

    await this.redisService.set(`captcha_${address}`, code, 5 * 60)

    await this.emailService.sendMail({
      to: address,
      subject: '注册验证码',
      html: `<p>你的注册验证码是 ${code}</p>`,
    })
    return `发送成功: ${code}`
  }

  @Post('login')
  async userLogin(@Body() loginUser: LoginUserDto, @Req() req: Request) {
    return await this.userService.login(loginUser, false, req)
  }

  @Get('login-hisitory')
  async userLoginHistory(@Query('pageNo') pageNo: number, @Query('pageSize') pageSize: number, @UserInfo('username') username: string) {
    return await this.userService.getLoginHisitory(pageNo, pageSize, username)
  }

  @Post('admin/login')
  async adminLogin(@Body() loginUser: LoginUserDto) {
    return await this.userService.login(loginUser, true)
  }

  @Get(['logout', 'admin/logout'])
  @RequireLogin()
  async userLogout(@UserInfo('userId') userId: number) {
    return await this.userService.logout(userId)
  }

  @Get('refresh')
  async refresh(@Query('refresh_token') refresh_token: string) {
    try {
      const data = this.jwtService.verify(refresh_token)
      const user = await this.userService.findUserById(data.userId)

      const { accessToken, refreshToken } = await this.userService.getJwtToken(user)
      const vo = new RefreshTokenVo()
      vo.accessToken = accessToken
      vo.refreshToken = refreshToken

      return vo
    }
    catch {
      throw new UnauthorizedException('token 已失效，请重新登录')
    }
  }

  @Get('admin/refresh')
  async adminRefresh(@Query('refreshToken') refresh_token: string) {
    try {
      const data = this.jwtService.verify(refresh_token)
      const user = await this.userService.findUserById(data.userId)

      const { accessToken, refreshToken } = await this.userService.getJwtToken(user)
      const vo = new RefreshTokenVo()
      vo.accessToken = accessToken
      vo.refreshToken = refreshToken

      return vo
    }
    catch {
      throw new UnauthorizedException('admin token 已失效，请重新登录')
    }
  }

  @Get('info')
  @RequireLogin()
  async getUserInfo(@UserInfo('userId') userId: number) {
    return await this.userService.getUserInfoById(userId)
  }

  @Post(['update', 'admin/update'])
  @RequireLogin()
  async updateUserInfo(@UserInfo('userId') userId: number, @Body() updateUserDto: UpdateUserDto) {
    const res = await this.userService.updateUserInfoById(userId, updateUserDto)

    this.redisService.del(`update_user_captcha_${updateUserDto.email}`)
    return res
  }

  @Get('update/captcha')
  @RequireLogin()
  async updateCaptcha(@UserInfo('email') address: string) {
    const code = Math.random().toString().slice(2, 8)

    await this.redisService.set(`update_user_captcha_${address}`, code, 10 * 60)
    await this.emailService.sendMail({
      to: address,
      subject: '更改用户信息验证码',
      html: `<p>你的验证码是 ${code}</p>`,
    })
    return `发送成功: ${code}`
  }

  @Post(['update_password', 'admin/update_password'])
  async updatePassword(@Body() passwordDto: UpdateUserPasswordDto) {
    const res = await this.userService.updatePassword(passwordDto)

    this.redisService.del(`update_password_captcha_${passwordDto.email}`)
    return res
  }

  @Get('update_password/captcha')
  async updatePasswordCaptcha(@Query('address') address: string) {
    const code = Math.random().toString().slice(2, 8)

    await this.redisService.set(`update_password_captcha_${address}`, code, 10 * 60)
    await this.emailService.sendMail({
      to: address,
      subject: '更改密码验证码',
      html: `<p>你的更改密码验证码是 ${code}</p>`,
    })
    return `发送成功: ${code}`
  }

  @Post('freeze')
  async freeze(@Body('id') userId: number) {
    await this.userService.freezeUserById(userId)
    return 'success'
  }

  @Get('list')
  @RequireLogin()
  async list(
    @Query('pageNo', new DefaultValuePipe(1), generateParseIntPipe('pageNo')) pageNo: number,
    @Query('pageSize', new DefaultValuePipe(2), generateParseIntPipe('pageSize')) pageSize: number,
    @Query('username') username: string,
    @Query('roles') nickName: string,
    @Query('email') email: string,
  ) {
    return await this.userService.findUsers(username, nickName, email, pageNo, pageSize)
  }

  @Get('test')
  @RequireLogin()
  @RequirePermission('ddd')
  async aaa() {
    return 'aaa'
  }
}
